<!DOCTYPE html>
<html lang="zh" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="description" content="fusion-docs">
<meta name="generator" content="Paradox, paradox-material-theme=0.6.0, mkdocs-material=3.0.3">

<meta name="lang:clipboard.copy" content="Copy to clipboard">
<meta name="lang:clipboard.copied" content="Copied to clipboard">
<meta name="lang:search.language" content="">
<meta name="lang:search.pipeline.stopwords" content="true">
<meta name="lang:search.pipeline.trimmer" content="true">
<meta name="lang:search.result.none" content="No matching documents">
<meta name="lang:search.result.one" content="1 matching document">
<meta name="lang:search.result.other" content="# matching documents">
<meta name="lang:search.tokenizer" content="[\s\-]+">


<meta name="description" content="fusion-docs">
<link rel="shortcut icon" href="../assets/images/favicon.png">
<title>Akka Extension（扩展） · Akka Fusion</title>
<link rel="stylesheet" href="../assets/stylesheets/application.451f80e5.css">
<link rel="stylesheet" href="../assets/stylesheets/application-palette.22915126.css">
<meta name="theme-color" content="#3f51b5" />
<link rel="stylesheet" href="../lib/material__tabs/dist/mdc.tabs.min.css">
<link rel="stylesheet" href="../lib/prettify/prettify.css">
<script src="../assets/javascripts/modernizr.1aa3b519.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,700|Roboto+Mono">
<style>
body,input{font-family:"Roboto","Helvetica Neue",Helvetica,Arial,sans-serif}
code,kbd,pre{font-family:"Roboto Mono","Courier New",Courier,monospace}
</style>
<link rel="stylesheet" href="../assets/fonts/font-awesome.css">
<link rel="stylesheet" href="../assets/fonts/material-icons.css">
<link rel="stylesheet" href="../assets/stylesheets/paradox-material-theme.css">
</head>
<body
data-md-color-primary="indigo"
data-md-color-accent="red"
>
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" data-md-component="overlay" for="__drawer"></label>
<header class="md-header" data-md-component="header">
<nav class="md-header-nav md-grid">
<div class="md-flex">
<div class="md-flex__cell md-flex__cell--shrink">
<a href="../index.html" title="Akka Fusion" class="md-header-nav__button md-logo">
<i class="md-icon">local_library</i>
</a>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--menu md-header-nav__button" for="__drawer"></label>
</div>
<div class="md-flex__cell md-flex__cell--stretch">
<div class="md-flex__ellipsis md-header-nav__title" data-md-component="title">
<span class="md-header-nav__topic">
Akka Fusion
</span>
<span class="md-header-nav__topic">
Akka Extension（扩展）
</span>
</div>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<label class="md-icon md-icon--search md-header-nav__button" for="__search"></label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query" data-md-state="active">
<label class="md-icon md-search__icon" for="__search"></label>
<button type="reset" class="md-icon md-search__icon" data-md-component="reset" tabindex="-1">&#xE5CD;</button>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="result">
<div class="md-search-result__meta">
Type to start searching
</div>
<ol class="md-search-result__list"></ol>
</div>
</div>
</div>
</div>
</div>

</div>
<div class="md-flex__cell md-flex__cell--shrink">
<div class="md-header-nav__source">
<a href="https://github.com/akka-fusion/akka-fusion"
title="Go to repository"
class="md-source"
data-md-source="github">
<div class="md-source__icon">
<i class="fa fa-github"></i>
</div>
<div class="md-source__repository">
akka-fusion/akka-fusion
</div>
</a>

</div>
</div>
</div>
</nav>
</header>

<div class="md-container">
<main class="md-main">
<div class="md-main__inner md-grid" data-md-component="container">
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" data-md-level="0" style="visibility: hidden">
<label class="md-nav__title md-nav__title--site" for="drawer">
<a href="../index.html" title="Akka Fusion" class="md-nav__button md-logo">
<span class="md-nav__button md-logo">
<i class="md-icon">local_library</i>
</a>
<a href="../index.html" title="Akka Fusion">
Akka Fusion
</a>
</label>
<div class="md-nav__source">
<a href="https://github.com/akka-fusion/akka-fusion"
title="Go to repository"
class="md-source"
data-md-source="github">
<div class="md-source__icon">
<i class="fa fa-github"></i>
</div>
<div class="md-source__repository">
akka-fusion/akka-fusion
</div>
</a>

</div>
<ul>
  <li><a href="../intro/index.html" class="page">简介</a></li>
  <li><a href="../core/index.html" class="page">核心</a>
  <ul>
    <li><a href="../core/akka-extension.html" class="active page">Akka Extension（扩展）</a></li>
    <li><a href="../core/http-route.html" class="page">Http Route（异步处理器）</a></li>
    <li><a href="../core/fusion-core.html" class="page">FusionCore</a></li>
  </ul></li>
  <li><a href="../http/index.html" class="page">HTTP</a>
  <ul>
    <li><a href="../http/getting.html" class="page">开始</a></li>
    <li><a href="../http/management.html" class="page">管理API</a></li>
    <li><a href="../http/interceptor-chain.html" class="page">Interceptor Chain（拦截器链）</a></li>
  </ul></li>
  <li><a href="../discovery-client/index.html" class="page">服务注册、发现（Client）</a>
  <ul>
    <li><a href="../discovery-client/nacos.html" class="page">连接 Nacos</a></li>
  </ul></li>
  <li><a href="../http-gateway/index.html" class="page">HTTP 代理网关</a></li>
  <li><a href="../jdbc/index.html" class="page">Jdbc</a></li>
  <li><a href="../slick/index.html" class="page">Slick</a></li>
  <li><a href="../mybatis/index.html" class="page">MyBatis</a>
  <ul>
    <li><a href="../mybatis/getting.html" class="page">起步</a></li>
    <li><a href="../mybatis/configuration.html" class="page">配置</a></li>
  </ul></li>
  <li><a href="../data-mongodb/index.html" class="page">Data Mongodb</a></li>
  <li><a href="../data-kafka/index.html" class="page">Data Kafka</a>
  <ul>
    <li><a href="../data-kafka/getting.html" class="page">开始</a></li>
    <li><a href="../data-kafka/producer.html" class="page">Kafka Producer</a></li>
    <li><a href="../data-kafka/consumer.html" class="page">Kafka Consumer</a></li>
  </ul></li>
  <li><a href="../inject/index.html" class="page">依赖管理</a>
  <ul>
    <li><a href="../inject/guice.html" class="page">使用 Guice 进行类依赖管理</a></li>
  </ul></li>
  <li><a href="../log/index.html" class="page">日志</a></li>
  <li><a href="../configuration/index.html" class="page">配置</a>
  <ul>
    <li><a href="../configuration/core.html" class="page">Fusion Core 配置</a></li>
    <li><a href="../configuration/http.html" class="page">Fusion HTTP 配置</a></li>
    <li><a href="../configuration/http-gateway.html" class="page">Fusion HTTP Gateway 配置</a></li>
    <li><a href="../configuration/jdbc.html" class="page">Fusion JDBC 配置</a></li>
    <li><a href="../configuration/slick.html" class="page">Fusion Slick 配置</a></li>
    <li><a href="../configuration/mybatis.html" class="page">Fusion Mybatis 配置</a></li>
    <li><a href="../configuration/mongodb.html" class="page">Fusion Mongodb 配置</a></li>
    <li><a href="../configuration/kafka.html" class="page">Fusion Kafka 配置</a></li>
  </ul></li>
  <li><a href="../reactivemanifesto.html" class="page">反应式宣言 2.0</a></li>
</ul>
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul>
  <li><a href="../core/akka-extension.html#akka-extension-扩展-" class="header">Akka Extension（扩展）</a>
  <ul>
    <li><a href="../core/akka-extension.html#从配置加载" class="header">从配置加载</a></li>
    <li><a href="../core/akka-extension.html#构建扩展" class="header">构建扩展</a></li>
    <li><a href="../core/akka-extension.html#通过akka-extension来管理资源" class="header">通过Akka Extension来管理资源</a></li>
    <li><a href="../core/akka-extension.html#通过akka-extension来管理服务-依赖-" class="header">通过Akka Extension来管理服务（依赖）</a></li>
  </ul></li>
</ul>
</nav>

</nav>
<ul style="display: none">
<li class="md-nav__item md-version" id="project.version">
<label class="md-nav__link" for="__version">
<i class="md-icon" title="Version">label_outline</i> 2.0.6
</label>
</li>
</ul>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary">
<label class="md-nav__title" for="__toc">Table of contents</label>
<ul>
  <li><a href="../core/akka-extension.html#akka-extension-扩展-" class="header">Akka Extension（扩展）</a>
  <ul>
    <li><a href="../core/akka-extension.html#从配置加载" class="header">从配置加载</a></li>
    <li><a href="../core/akka-extension.html#构建扩展" class="header">构建扩展</a></li>
    <li><a href="../core/akka-extension.html#通过akka-extension来管理资源" class="header">通过Akka Extension来管理资源</a></li>
    <li><a href="../core/akka-extension.html#通过akka-extension来管理服务-依赖-" class="header">通过Akka Extension来管理服务（依赖）</a></li>
  </ul></li>
</ul>
</nav>

</div>
</div>
</div>
<div class="md-content">
<article class="md-content__inner md-typeset">
<div class="md-content__searchable">
<h1><a href="#akka-extension-扩展-" name="akka-extension-扩展-" class="anchor"><span class="anchor-link"></span></a>Akka Extension（扩展）</h1>
<p>Akka Extension是Akka提供的一套可插拔的、用来增强Akka能力的机制，<code>akka-cluster</code>等很多内建功能也是基于它实现的。同时，Akka Extension还提供了某种程度上的依赖管理功能，Fusion也基于它实现了**akka-fusion**框架的模块化管理。</p>
<p>Akka Extension提供了两个基本组件：<code>Extension</code>和<code>ExtensionId</code>。每个Akka扩展在同一个<code>ActorSystem</code>内保证只加载一次，你可以选择按需加载，也可以选择随<code>ActorSystem</code>创建时即加载。有关这部分的内容参考接下来的 <a href="#从配置加载">从配置加载</a> 。</p>
<p>这样，在你的应用中只需要全局保证一个ActorSystem即可，其它的服务、资源都可以通过 Akka Extension 来维护。同时，你可以很自然的在自己的Akka Extension实例内部引用其它的Akka Extension（需要保证它们都使用同一个ActorSystem）。 这可能是在不使用IOC（如Spring、Guice等）情况下最好的进行依赖管理机制之一。</p>
<h2><a href="#从配置加载" name="从配置加载" class="anchor"><span class="anchor-link"></span></a>从配置加载</h2>
<pre class="prettyprint"><code class="language-hocon">akka {
  # 用于为Akka制作的第三方扩展库，需要随ActorSystem一起加载。
  # 若最终用户需要在`application.conf`中配置扩展，应使用`extensions`属性配置。
  library-extensions = ${?akka.library-extensions} [&quot;akka.serialization.SerializationExtension&quot;]

  # 在此列出需要加载的多个自定义扩展，需要使用类的全限定名。
  extensions = []
}
</code></pre>
<h2><a href="#构建扩展" name="构建扩展" class="anchor"><span class="anchor-link"></span></a>构建扩展</h2>
<p>akka-fusion在提供了 <code>FusionExtension</code> 帮助trait来构建Akka Extension。</p>
<pre class="prettyprint"><a class="icon go-to-source" href="https://github.com/akka-fusion/akka-fusion/tree/master/fusion-core/src/main/scala/fusion/common/extension/FusionExtension.scala#L25-L30" target="_blank" title="Go to snippet source"></a><code class="language-scala">trait FusionExtension extends Extension {
  val classicSystem: ExtendedActorSystem

  val configuration: Configuration = Configuration(classicSystem.settings.config)
  def typedSystem: ActorSystem[Nothing] = classicSystem.toTyped
}</code></pre>
<p><code>FusionExtension</code>在默认<code>Extension</code>基础之上添加了<code>ActorSystem[T]</code>和<code>akka.actor.ActorSystem</code>引用，提供了<code>Configuration</code>（对Lightbend Config的增强包装）。</p>
<h2><a href="#通过akka-extension来管理资源" name="通过akka-extension来管理资源" class="anchor"><span class="anchor-link"></span></a>通过Akka Extension来管理资源</h2>
<p>接下来为<code>FusionJdbc</code>作为示例，说明<code>FusionExtension</code>是怎样来管理我们的数据库访问资源的。<code>FusionJdbc</code>管理了一个或多个数据库连接池，连接池通过 <a href="https://github.com/brettwooldridge/HikariCP">HikariCP</a> 实现。</p>
<pre class="prettyprint"><a class="icon go-to-source" href="https://github.com/akka-fusion/akka-fusion/tree/master/fusion-jdbc/src/main/scala/fusion/jdbc/FusionJdbc.scala#L47-L57" target="_blank" title="Go to snippet source"></a><code class="language-scala">class FusionJdbc private (override val classicSystem: ExtendedActorSystem) extends FusionExtension {
  val components = new JdbcComponents(classicSystem)
  FusionCore(classicSystem).shutdowns.beforeActorSystemTerminate(&quot;StopFusionJdbc&quot;) { () =&gt;
    components.closeAsync()(classicSystem.dispatcher)
  }
  def component: HikariDataSource = components.component
}

object FusionJdbc extends FusionExtensionId[FusionJdbc] {
  override def createExtension(system: ExtendedActorSystem): FusionJdbc = new FusionJdbc(system)
}</code></pre>
<p><code>FusionJdbc</code>将由Akka保证在同一个ActorSystem中只被实例化一次，就像Spring框架里的<code>@Service</code>注解、Guice框架的<code>Singleton</code>注解一样，它们都是 <strong>单例</strong> 。</p>
<pre class="prettyprint"><a class="icon go-to-source" href="https://github.com/akka-fusion/akka-fusion/tree/master/fusion-jdbc/src/main/scala/fusion/jdbc/FusionJdbc.scala#L32-L43" target="_blank" title="Go to snippet source"></a><code class="language-scala">final private[jdbc] class JdbcComponents(system: ExtendedActorSystem)
    extends Components[HikariDataSource](JdbcConstants.PATH_DEFAULT) {
  override def configuration: Configuration = Configuration(system.settings.config)

  override protected def componentClose(c: HikariDataSource): Future[Done] = Future.successful {
    c.close()
    Done
  }

  override protected def createComponent(id: String): HikariDataSource =
    JdbcUtils.createHikariDataSource(configuration.getConfig(id))
}</code></pre>
<p><code>JdbcComponents</code>继承了<code>Components</code>，<code>Components</code>提供了一个保存同一类型组件的多个实例的优秀方案。它基于 Lightbend Config 实现了可配置化，通过构造函数传入的配置路径（id）来决定引用哪一个配置，并保存id的实例的对应关系。</p>
<p>请关注<code>FusionCore(system).shutdowns.beforeActorSystemTerminate</code>这行代码，它使用<code>CoordinatedShutdown</code>来协调资源的关闭，它将在<code>ActorSystem</code>终止前关闭所有数据库连接池。更多内容请参阅： <a href="fusion-core.html#shutdowns">FusionCore#shutdowns</a></p>
<h4><a href="#components" name="components" class="anchor"><span class="anchor-link"></span></a>Components</h4>
<p><code>Components</code> 提供代码实现如下：</p>
<pre class="prettyprint"><a class="icon go-to-source" href="https://github.com/akka-fusion/akka-fusion/tree/master/fusion-core/src/main/scala/fusion/common/component/Components.scala#L30-L69" target="_blank" title="Go to snippet source"></a><code class="language-scala">abstract class Components[T](DEFAULT_ID: String) extends StrictLogging {
  protected val components = mutable.Map.empty[String, T]

  def configuration: Configuration

  protected def createComponent(id: String): T
  protected def componentClose(c: T): Future[Done]

  def component: T = lookup(DEFAULT_ID)

  final def lookup(id: String): T = synchronized(lookupComponent(id))

  protected def lookupComponent(id: String): T = components.getOrElseUpdate(id, createComponent(id))

  final def register(id: String, other: T, replaceExists: Boolean = false): T =
    synchronized(registerComponent(id, other, replaceExists))

  protected def registerComponent(id: String, other: T, replaceExists: Boolean): T = {
    require(id != DEFAULT_ID, s&quot;id不能为默认配置ID，$id == $DEFAULT_ID&quot;)
    val isReplace = configuration.getOrElse(id + &quot;.replace-exists&quot;, replaceExists)
    components.get(id).foreach {
      case c if isReplace =&gt;
        try {
          Await.ready(componentClose(c), 30.seconds)
        } catch {
          case e: Throwable =&gt;
            logger.error(s&quot;registerComponent replace exists component 30s timeout error: ${e.toString}；id: $id&quot;, e)
        }
        components.remove(id)
      case _ =&gt;
        throw new IllegalAccessException(s&quot;id重复，$id&quot;)
    }
    components.put(id, other)
    other
  }

  def closeAsync()(implicit ec: ExecutionContext): Future[Done] = synchronized {
    Future.sequence(components.valuesIterator.map(componentClose).toList).map(_ =&gt; Done)
  }
}</code></pre>
<h2><a href="#通过akka-extension来管理服务-依赖-" name="通过akka-extension来管理服务-依赖-" class="anchor"><span class="anchor-link"></span></a>通过Akka Extension来管理服务（依赖）</h2>
<p>修定你有3个服务：</p>
<ul>
  <li>FileService：统一的文件服务，如提供用户头像链接</li>
  <li>UserService：用户服务</li>
  <li>LoginService：实现用户登录、注册等业务逻辑</li>
</ul>
<p>你可以如下定义3个服务</p>
<pre class="prettyprint"><a class="icon go-to-source" href="https://github.com/akka-fusion/akka-fusion/tree/master/fusion-docs/src/main/scala/docs/extension/customservice/CustomService.scala" target="_blank" title="Go to snippet source"></a><code class="language-scala">/*
 * Copyright 2019 helloscala.com
 *
 * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package docs.extension.customservice

import akka.actor.typed.ActorSystem
import fusion.common.extension.{ TypedExtension, TypedExtensionId }
import helloscala.common.exception.HSUnauthorizedException
import helloscala.common.util.{ DigestUtils, StringUtils }

import scala.concurrent.Future

case class LoginDTO(account: String, password: String)
case class LoginBO(id: String, nickname: String)
case class UserBO(id: String, nickname: String, avatarId: String, avatarUrl: String)
case class UserDO(id: String, nickname: String, avatarId: String, password: String, salt: String)

class UserRepository {
  def findByAccount(account: String): Future[UserDO] =
    Future.successful(UserDO(StringUtils.randomString(24), account, StringUtils.randomString(24), &quot;password&quot;, &quot;salt&quot;))

  def findById(id: String): Future[UserDO] =
    Future.successful(UserDO(id, &quot;用户&quot;, StringUtils.randomString(24), &quot;password&quot;, &quot;salt&quot;))
}

class FileService private (override val typedSystem: ActorSystem[Nothing]) extends TypedExtension {
  def findUrlById(fileId: String): Future[String] = Future.successful {
    s&quot;http://localhost:9999/file/$fileId.png&quot;
  }
}

object FileService extends TypedExtensionId[FileService] {
  override def createExtension(system: ActorSystem[_]): FileService = new FileService(system)
}

class UserService private (override val typedSystem: ActorSystem[Nothing]) extends TypedExtension {
  import typedSystem.executionContext
  private val fileService = FileService(typedSystem)
  private val userRepository = new UserRepository()

  def findBOById(id: String): Future[UserBO] = {
    userRepository.findById(id).flatMap { user =&gt;
      fileService.findUrlById(user.avatarId).map { url =&gt;
        UserBO(user.id, user.nickname, user.avatarId, url)
      }
    }
  }

  def findByAccount(account: String): Future[UserDO] = {
    userRepository.findByAccount(account)
  }
}

object UserService extends TypedExtensionId[UserService] {
  override def createExtension(system: ActorSystem[_]): UserService = new UserService(system)
}

class LoginService private (override val typedSystem: ActorSystem[Nothing]) extends TypedExtension {
  import typedSystem.executionContext
  private val userService = UserService(typedSystem)

  def login(dto: LoginDTO): Future[LoginBO] = {
    userService.findByAccount(dto.account).map {
      case user if user.password == DigestUtils.sha256Hex(dto.password + user.salt) =&gt;
        LoginBO(user.id, user.nickname)
      case _ =&gt;
        throw HSUnauthorizedException(&quot;密码不匹配&quot;)
    }
  }
}

object LoginService extends TypedExtensionId[LoginService] {
  override def createExtension(system: ActorSystem[_]): LoginService = new LoginService(system)
}</code></pre>
<p>通过以上代码，你看到了怎样使用Akka Extension来实现服务的依赖管理。所有的服务之间只有一个显示依赖：<code>ActorSystem</code>。因为我们的框架是基于Akka的，所以我们认为显示依赖<code>ActorSystem</code>并不是一个问题。</p>
</div>
<div>
<a href="https://github.com/akka-fusion/akka-fusion/tree/master/fusion-docs/src/main/paradox/core/akka-extension.md" title="Edit this page" class="md-source-file md-edit">
Edit this page
</a>
</div>
<div class="print-only">
<span class="md-source-file md-version">
2.0.6
</span>
</div>
</article>
</div>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-nav">
<nav class="md-footer-nav__inner md-grid">
<a href="../core/index.html" title="核心" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
</div>
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Previous
</span>
核心
</span>
</div>
</a>
<a href="../core/http-route.html" title="Http Route（异步处理器）" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
<span class="md-flex__ellipsis">
<span class="md-footer-nav__direction">
Next
</span>
Http Route（异步处理器）
</span>
</div>
<div class="md-flex__cell md-flex__cell--shrink">
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
</div>
</a>
</nav>
</div>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-footer-copyright">
Powered by
<a href="https://github.com/lightbend/paradox">Paradox</a>
and
<a href="https://jonas.github.io/paradox-material-theme/">Paradox Material Theme</a>

</div>
<div class="md-footer-social">
<a href="https://akka-fusion.github.io/akka-fusion/" class="md-footer-social__link fa fa-globe"></a><a href="https://github.com/akka-fusion" class="md-footer-social__link fa fa-github"></a><a href="https://weibo.com/yangbajing" class="md-footer-social__link fa fa-globe"></a>
</div>

</div>
</div>
</footer>

</div>
<script src="../assets/javascripts/application.583bbe55.js"></script>
<script src="../assets/javascripts/paradox-material-theme.js"></script>
<script>app.initialize({version:"0.17",url:{base:"../."}})</script>
<script type="text/javascript" src="../lib/prettify/prettify.js"></script>
<script type="text/javascript" src="../lib/prettify/lang-scala.js"></script>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function(event) {
window.prettyPrint && prettyPrint();
});
</script>
</body>
</html>
